/* #define TEMP_VERSION /* if defined, temporary experimental
							version of PGP */
/* pgp.c -- main module for PGP.
   PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.

   Synopsis:  PGP uses public-key encryption to protect E-mail. 
   Communicate securely with people you've never met, with no secure
   channels needed for prior exchange of keys.	PGP is well featured and
   fast, with sophisticated key management, digital signatures, data
   compression, and good ergonomic design.

   The original PGP version 1.0 was written by Philip Zimmermann, of
   Phil's Pretty Good(tm) Software.  Many parts of later versions of 
   PGP were developed by an international collaborative effort, 
   involving a number of contributors, including major efforts by:
   Branko Lankester <branko@hacktic.nl>
   Hal Finney <74076.1041@compuserve.com>
   Peter Gutmann <pgut1@cs.aukuni.ac.nz>
   Other contributors who ported or translated or otherwise helped include:
   Jean-loup Gailly in France
   Hugh Kennedy in Germany
   Lutz Frank in Germany
   Cor Bosman in The Netherlands
   Felipe Rodriquez Svensson in The Netherlands
   Armando Ramos in Spain
   Miguel Angel Gallardo Ortiz in Spain
   Harry Bush and Maris Gabalins in Latvia
   Zygimantas Cepaitis in Lithuania
   Alexander Smishlajev
   Peter Suchkow and Andrew Chernov in Russia
   David Vincenzetti in Italy
   ...and others.


   (c) Copyright 1990-1996 by Philip Zimmermann.  All rights reserved.
   The author assumes no liability for damages resulting from the use
   of this software, even if the damage results from defects in this
   software.  No warranty is expressed or implied.

   Note that while most PGP source modules bear Philip Zimmermann's
   copyright notice, many of them have been revised or entirely written
   by contributors who frequently failed to put their names in their
   code.  Code that has been incorporated into PGP from other authors
   was either originally published in the public domain or is used with
   permission from the various authors.

   PGP is available for free to the public under certain restrictions.
   See the PGP User's Guide (included in the release package) for
   important information about licensing, patent restrictions on
   certain algorithms, trademarks, copyrights, and export controls.


   Philip Zimmermann may be reached at:
   Boulder Software Engineering
   3021 Eleventh Street
   Boulder, Colorado 80304	USA
   (303) 541-0140  (voice or FAX)
   email:  prz@acm.org


   PGP will run on MSDOS, Sun Unix, VAX/VMS, Ultrix, Atari ST, 
   Commodore Amiga, and OS/2.  Note:  Don't try to do anything with 
   this source code without looking at the PGP User's Guide.

   PGP combines the convenience of the Rivest-Shamir-Adleman (RSA)
   public key cryptosystem with the speed of fast conventional
   cryptographic algorithms, fast message digest algorithms, data
   compression, and sophisticated key management.  And PGP performs 
   the RSA functions faster than most other software implementations.  
   PGP is RSA public key cryptography for the masses.

   Uses RSA Data Security, Inc. MD5 Message Digest Algorithm
   as a hash for signatures.  Uses the ZIP algorithm for compression.
   Uses the ETH IPES/IDEA algorithm for conventional encryption.

   PGP generally zeroes its used stack and memory areas before exiting.
   This avoids leaving sensitive information in RAM where other users
   could find it later.  The RSA library and keygen routines also
   sanitize their own stack areas.	This stack sanitizing has not been
   checked out under all the error exit conditions, when routines exit
   abnormally.	Also, we must find a way to clear the C I/O library
   file buffers, the disk buffers, and cache buffers.

   Revisions:
   Version 1.0 -  5 Jun 91
   Version 1.4 - 19 Jan 92
   Version 1.5 - 12 Feb 92
   Version 1.6 - 24 Feb 92
   Version 1.7 - 29 Mar 92
   Version 1.8 - 23 May 92
   Version 2.0 -  2 Sep 92
   Version 2.1 -  6 Dec 92
   Version 2.2 -  6 Mar 93
   Version 2.3 - 13 Jun 93
   Version 2.3a-  1 Jul 93
   Version 2.4 -  6 Nov 93
   Version 2.5 -  5 May 94
   Version 2.6 - 22 May 94
   Version 2.6.1 - 29 Aug 94
   Version 2.6.2 - 11 Oct 94
   Version 2.6.2i - 7 May 95
   Version 2.6.3(i) - 18 Jan 96

 */


#include <ctype.h>
#ifndef AMIGA
#include <signal.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef UNIX
#include <sys/stat.h>
#endif

#include "system.h"
#include "mpilib.h"
#include "random.h"
#include "memfile.h"
#include "md5.h"
#include "crypto.h"
#include "keymgmt.h"
#include "language.h"
#include "pgp.h"
#include "exitpgp.h"
#include "rsaglue.h"
#include "noise.h"
#include "ipriv.h"

extern char mcguffin[]; /* userid search tag */

void IPrivClearResources();
void initsigs(void);

int EXT_FUNC InitIPriv()
{
	boolean nestflag = FALSE;
	boolean armor_flag = FALSE; /* -a option */
	boolean separate_signature = FALSE;
	boolean keyflag = FALSE;
	boolean encrypt_flag = FALSE;
	boolean conventional_flag = FALSE;
	boolean attempt_compression; /* attempt compression before encryption */
	char *p;
	byte ctb;

	int status = setjmp(jbuf);
	if(status != 0) return status;

#ifdef MACTC5
		ReInitGlobals();
#endif
	/* The various places one can get passwords from.
	 * We accumulate them all into two lists.  One is
	 * to try on keys only, and is stored in no particular
	 * order, while the other is of unknown purpose so
	 * far (they may be used for conventional encryption
	 * or decryption as well), and are kept in a specific
	 * order.  If any password in the general list is found
	 * to decode a key, it is moved to the key list.
	 * The general list is not grown after initialization,
	 * so the tail pointer is not used after this.
	 */

#ifndef MACTC5
	/*
	 * These must be personal; the system config file may not
	 * influence them.
	 */
	strcpy(globalRandseedName, "random.bin");

	/* Process the config file first.  Any command-line arguments will
	   override the config file settings */
#endif /* MACTC5 */

#ifdef VMS
#define TEMP "SYS$SCRATCH"
#else
#define TEMP "TMP"
#endif							/* VMS */
	check_expiration_date();	/* hobble any experimental version */

	/*
	 * Write to stdout if explicitly asked to, or in filter mode and
	 * no explicit file name was given.
	 */

#if defined(UNIX) || defined(VMS)
	umask(077); 				/* Make files default to private */
#endif

	initsigs(); 				/* Catch signals */
	noise();					/* Start random number generation */

	set_precision(MAX_UNIT_PRECISION);/* safest opening */

	return 0;
#ifdef MACTC5
}								/* pgp_dispatch */
#else
}								/* main */
#endif

void EXT_FUNC TermIPriv()
{
		IPrivClearResources();
}

#ifdef MSDOS
#include <dos.h>
static char *dos_errlst[] =
{
	"Write protect error",		/* LANG ("Write protect error") */
	"Unknown unit",
	"Drive not ready",			/* LANG ("Drive not ready") */
	"3", "4", "5", "6", "7", "8", "9",
	"Write error",				/* LANG ("Write error") */
	"Read error",				/* LANG ("Read error") */
	"General failure",
};

/* handler for msdos 'harderrors' */
#ifndef OS2
#ifdef __TURBOC__				/* Turbo C 2.0 */
static int dostrap(int errval)
#else
static void dostrap(unsigned deverr, unsigned errval)
#endif
{
	char errbuf[64];
	int i;
	sprintf(errbuf, "\r\nDOS error: %s\r\n", dos_errlst[errval]);
	i = 0;
	do
		bdos(2, (unsigned int) errbuf[i], 0);
	while (errbuf[++i]);
#ifdef __TURBOC__
	return 0;					/* ignore (fopen will return NULL) */
#else
	return;
#endif
}
#endif							/* MSDOS */
#endif

#if defined(DEBUG) && defined(linux)
#include <malloc.h>
#endif

/*
 * IPackClearResources: wipes and removes temporary files, also tries to wipe
 * the stack.
 */
void IPrivClearResources()
{
	char buf[STACK_WIPE];
	/* Merge any entropy we collected into the randseed.bin file */
	if (cryptRandOpen((struct IdeaCfbContext *)0) >= 0)
			cryptRandSave((struct IdeaCfbContext *)0);
	memset(buf, 0, sizeof(buf));		/* wipe stack */
}

int EXT_FUNC GetIPrivLastError(char *sBuffer, int nLength)
{
	strncpy(sBuffer, sErrorText, nLength);
	return nErrorCode;
}
